// 云函数入口文件
const cloud = require('wx-server-sdk')

cloud.init({
  env: cloud.DYNAMIC_CURRENT_ENV
})

const db = cloud.database()
const _ = db.command

//引用TcbRouter
const TcbRouter = require('tcb-router')

/**
 * 成功的数据结构
 */
const getSuccessData = (data = {}) => ({
  status: 200,
  data: {
    status: 0,
    data
  }
})

/**
 * 失败的数据结构
 */
const getFailData = (data = {}) => ({
  status: 401,
  data: {
    ...data
  }
})

// 云函数入口函数
exports.main = async (event, context) => {
  const app = new TcbRouter({
    event
  })

  /**
   * 精选案例中的初始化信息
   * 注意这里的返回数据，例如：精选案例/家居软装。仅仅需要10个，往下拉的时候会异步加载数据。
   */
  app.router('/examples/index', async (ctx, next) => {
    const {
      listCount,
      skipCount,
      cName
    } = event.other

    // 精选案例这个分类本身的id
    const parentId = '5de31d5fb0f80726901430ca'

    try {
      /**
       * cName有可能是“推荐”、“办公楼宇”、“商业展示”和“”家居软装。
       * 如果是“推荐”，那么是得不到数据的，需要返回“精选案例”下的listCount数量。
       * 如果是别的，那么直接使用resultCNameId.parentId所代表的种类id查找，返回数据。
       */
      const {
        data: resultCNameId
      } = await db.collection("categorys").where({
        name: cName
      }).get()

      const condition = resultCNameId.length > 0 ?
        // 根据所属分类查找
        {
          categoryId: resultCNameId[0]._id,
          status: 1,
          title: _.neq('轮播图')
        } :
        // 根据所属分类的父分类查找，这里的父分类是“精选案例”。
        {
          pCategoryId: parentId,
          status: 1,
          title: _.neq('轮播图')
        }

      const {
        list
      } = await db.collection("products")
        .aggregate()
        .lookup({
          from: 'collections',
          localField: 'collection',
          foreignField: '_id',
          as: 'collection'
        })
        .match(condition)
        .skip(skipCount * 1)
        .limit(listCount * 1)
        .sort({
          _id: -1
        })
        .project({
          categoryId: 0,
          pCategoryId: 0
        })
        .end()

      ctx.body = getSuccessData(list)

    } catch (error) {

      ctx.body = getFailData({
        status: 1,
        msg: '精选案例中的初始化失败。',
        error
      })

    }

  })

  /**
   * 精选案例中的每一篇文章的详细信息展示。
   * 浏览数，点赞数和留言板
   */
  app.router('/examples/detail', async (ctx, next) => {
    const {
      _id
    } = event.other

    try {
      const {
        data: productsData
      } = await db.collection("products").where({
        _id
      }).get()

      const {
        data: messages
      } = await db.collection('products_messages').where({
        _id: productsData.messages
      }).get()

      productsData.messages = messages

      ctx.body = getSuccessData(productsData)

    } catch (error) {

      ctx.body = getFailData({
        status: 1,
        msg: '精选案例中的详细内容初始化失败。',
        error
      })

    }
  })
  /**
   * 更新文章的阅读数和留言
   */
  app.router('/examples/detailUpdate', async (ctx, next) => {
    const {
      _id,
      viewingCount,
      likes,
      messages,
      collection,
      userInfo
    } = event.other

    /**
     * 对本文章的“阅读数”和“点赞数”的操作。
     * 如果数据库中的当前文章
     * 修改ProductModel中的likesIdList
     */
    let updateInfo = {}

    // 增加阅读数
    if (viewingCount) updateInfo.viewingCount = viewingCount

    // 收藏
    if (collection) updateInfo.collection = true

    try {
      await db.collection('products').where({
        _id
      }).update({
        data: updateInfo
      })

      const {
        data: productsData
      } = await db.collection('products').where({
        _id
      }).get()

      let resultData = {
        ...productsData[0]
      }

      // 填充messages
      if (resultData.messages) {
        const {
          messages
        } = resultData
        const {
          data
        } = await db.collection('products_messages').where({
          _id: messages
        }).get()

        resultData.messages = data
      }

      // 获取当前文章中最后的那五个图片。
      const {
        data: dataInfos
      } = await db.collection('yczs-info').where({}).get()
      const {
        bottomImages
      } = dataInfos[0]
      resultData.bottomImages = bottomImages

      ctx.body = getSuccessData(resultData)
    } catch (error) {
      ctx.body = getFailData({
        msg: '精选案例中的详细内容更新失败。',
        error: {
          _id,
          viewingCount,
          likes,
          messages,
          collection
        }
      })
    }

  })
  /**
   * 点赞和收藏
   */
  app.router('/examples/collection', async (ctx, next) => {

    const {
      _id: productId,
      userInfo,
      flag,
      flagClickLike
    } = event.other

    const {
      OPENID: openid,
      APPID: appid,
    } = cloud.getWXContext()

    let userId = null

    try {
      /**
       * 先检查是否有这个用户，如果没有，则将用户信息录入users集合中。
       */
      const {
        total: openIdTotal
      } = await db.collection('users-yczs').where({
        openid,
        appid,
      }).count()

      // 如果没有这个用户，这里记得要添加 userInfo
      if (0 === openIdTotal) {
        tempMsg = 'useryczs add error'

        const {
          _id
        } = await db.collection('users-yczs').add({
          data: {
            openid,
            appid,
            userInfo
          }
        })

        userId = _id

        // 如果有这个用户
      } else {
        const {
          data: {
            _id
          }
        } = await db.collection('users-yczs').where({
          openid,
          appid,
        }).get()

        userId = _id
      }

      /**
       * 检查collections集合中是否有文章id productId
       * 如果有，那么更新collection的值
       * 如果没有，那么就插入新元素到users集合，并且插入新元素到collections集合中。
       * 找到这篇文章
       */
      const {
        total: productTotal
      } = await db.collection('collections').where({
        productId
      }).count()

      /**
       * 如果有这篇文章
       */
      if (0 !== productTotal) {
        const {
          data
        } = await db.collection('collections').where({
          productId
        }).get()

        tempMsg = data[0]

        let {
          list
        } = data[0]

        /**
         * 找到这个文章中的list，并且设置flag的值
         */
        list.forEach(e => {
          if (e.appid === appid && e.openid === openid) {
            if (undefined !== flag) e.flag = flag
            else if (undefined !== flagClickLike) e.flagClickLike = flagClickLike
          }
        })

        await db.collection('collections').where({
          productId
        }).update({
          data: {
            list
          }
        })

        /**
         * 如果没有这篇文章，就添加。
         */
      } else {
        const {
          _id: collectionId
        } = await db.collection('collections').add({
          data: {
            productId,
            list: [{
              appid,
              openid,
              flag,
              flagClickLike
            }]
          }
        })

        /**
         * 同时存储id到集合products中的collection中
         * 注意：这里的更新是失败的，数据库中不会有collection字段。
         */
        await db.collection('products').where({
          _id: productId
        }).update({
          collection: collectionId
        })
      }

      ctx.body = getSuccessData()

    } catch (error) {
      ctx.body = getFailData({
        msg: '精选案例中的详细内容更新失败。',
        error
      })
    }
  })
  /**
   * 获取当前用户收藏的文章列表
   */
  app.router('/examples/getCollections', async (ctx, next) => {
    const {
      APPID: appid,
      OPENID: openid,
    } = cloud.getWXContext()

    try {
      let {
        data
      } = await db.collection("collections").where({
        list: {
          appid,
          openid,
          flag: true
        }
      }).get()

      const idList = data.length === 0 ? [] : data.map(e => e.productId)

      // 这真是一种超级低效的写法
      const result = await Promise.all(idList.map(_id =>
        db.collection('products').where({
          _id
        }).get()
      ))

      let list = []
      result.forEach(item => {
        item.data.forEach(e => {
          list.push(e)
        })
      })

      ctx.body = getSuccessData({
        list,
      })
    } catch (error) {
      ctx.body = getFailData({
        status: 1,
        msg: '获取当前用户收藏的文章列表失败',
        error
      })
    }
  })
  /**
   * 获取精选案例的中轮播图和tabs
   */
  app.router('/examples/swiperPictures', async (ctx, next) => {
    const pCategoryId = '5de31d5fb0f80726901430ca' // 精选案例这个分类本身的id
    const categoryId = '5e4790d412dd9731b45b9260' // 精选案例中的轮播图独占一个分类，这是这个分类的id

    try {
      let {
        list: dataTabs
      } = await db.collection("categorys").aggregate()
        .match({
          name: _.neq('轮播图'),
          parentId: pCategoryId
        })
        .project({
          _id: 0,
          name: 1
        })
        .end()

      let {
        list
      } = await db.collection("products").aggregate()
        .match({
          categoryId
        })
        .project({
          _id: 0,
          imgs: 1
        })
        .end()

      dataTabs = [{
        name: '推荐'
      }].concat(dataTabs)

      ctx.body = getSuccessData({
        dataTabs,
        imgs: list[0].imgs
      })
    } catch (error) {

      ctx.body = getFailData({
        status: 1,
        msg: '获取精选案例的中轮播图失败。',
        error
      })

    }

  })

  return app.serve()
}